/* plot.h */

#ifndef DODO_PLOT_H
#define DODO_PLOT_H

#include <dodo_plot/kernel/plotfwd.h>
#include <dodo_plot/kernel/basic_elements.h>
#include <dodo_plot/kernel/plotter.h>
#include <dodo_plot/kernel/basic_utils.h>
#include <dodo_plot/projector/projector.h>
#include <cairomm/cairomm.h>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <list>

namespace dodo_plot
{

class Plot_Data_Base;

template<class X_T, class Y_T, class X_Proj_T, class Y_Proj_T>
class Plot_Data;

/**
 * 数据曲线图.
 * 目前有两种方式构造:
 *	- 由表示y数据的一对迭代器来构造
 *	- 由表示x数据的一对迭代器和表示y数据开始的一个迭代器来构造
 * 需要指定y(和x)的数据范围.
 * 仅由y数据构造时, x数据按0 ~ SIZE - 1处理.
 *
 * TODO: 将提供为任意类型数据绘图的功能.
 */
/// 数据曲线图
class Plot
{
public:
//	void draw(Canvas& canvas, const Position& pos) const;
//
//	double width() const { return 1.0; }
//	double height() const { return 1.0; }
public:
	void draw(const Plotter& plotter) const;
	double width() const;
	double height() const;
	Position local_pos() const;

public:

//	template<class Y_C_T, class Y_T>
//	Plot(const Y_C_T<Y_T>& y);

//	template<class Y_C_T, class Y_T>
//	Plot(const Y_C_T<Y_T>& y, 
//		const Y_T& y_min, const Y_T& y_max
//		);
//
//	template<class X_C_T, class X_T, class Y_C_T, class Y_T>
//	Plot(const X_C_T<X_T>& x, const Y_C_T<Y_T>& y, 
//		const X_T& x_min, const X_T& x_max,
//		const Y_T& y_min, const Y_T& y_max
//	    );

	template<class Y_Iter, class Y_T>
	Plot(Y_Iter y_b, Y_Iter y_e, 
		const Y_T& y_min, const Y_T& y_max
	    );
	
	template<class X_Iter, class X_T, class Y_Iter, class Y_T>
	Plot(X_Iter x_b, X_Iter x_e,
		Y_Iter y_b,
		const X_T& x_min, const X_T& x_max,
		const Y_T& y_min, const Y_T& y_max
	    );

public:
	void set_line_color(const Color& color);
	void set_line_width(double width);

public:
	Plot(const Plot& orig);

	~Plot();

	Plot& operator= (const Plot& orig);


private:
	Plot_Data_Base* data_p_;
	
//	double line_width_;
//	Color line_color_;
};

class Plot_Data_Base
{
	friend class Plot;

private:
	int use_count_;

protected:
	Plot_Data_Base() : use_count_(1) { }
	virtual ~Plot_Data_Base() { }

	virtual void draw(const Plotter& plotter) const = 0;
	virtual double width() const = 0;
	virtual double height() const = 0;
	virtual Position local_pos() const = 0;
	virtual void set_line_color(const Color&) = 0;
	virtual void set_line_width(double) = 0;

};

template<class X_T, class Y_T, class X_Proj_T, class Y_Proj_T>
class Plot_Data : public Plot_Data_Base
{
	friend class Plot;
private:
	void set_line_color(const Color& color);
	void set_line_width(double width);

	void draw(const Plotter& plotter) const;
	double width() const { return 1.0;}
	double height() const { return 1.0;}
	Position local_pos() const 
	{ 
		return Position(
			x_proj_(x_min_),
			x_proj_(x_max_),
			y_proj_(y_max_),
			y_proj_(y_min_)
			);
	}

private:
	// 4 args
	template<class Y_Iter>
	Plot_Data(Y_Iter y_b, Y_Iter y_e, 
		const Y_T& y_min, const Y_T& y_max);

	// 5 args
	template<class Y_Iter>
	Plot_Data(Y_Iter y_b, Y_Iter y_e,
		const Y_T& y_min, const Y_T& y_max,
		Y_Proj_T y_proj);

	// 7 args
	template<class X_Iter, class Y_Iter>
	Plot_Data(X_Iter x_b, X_Iter x_e, Y_Iter y_b,
		const X_T& x_min, const X_T& x_max,
		const Y_T& y_min, const Y_T& y_max);

	// 9 args
	template<class X_Iter, class Y_Iter>
	Plot_Data(X_Iter x_b, X_Iter x_e, Y_Iter y_b,
		const X_T& x_min, const X_T& x_max,
		const Y_T& y_min, const Y_T& y_max,
		const X_Proj_T& x_proj,
		const Y_Proj_T& y_proj);

private:
	std::list<X_T> x_;
	std::list<Y_T> y_;
	X_Proj_T x_proj_;
	Y_Proj_T y_proj_;

	X_T x_min_, x_max_;
	Y_T y_min_, y_max_;

	Color line_color_;
	double line_width_;
};



}

#include <dodo_plot/widget/plot.tcc>

#endif //DODO_PLOT_H

